﻿#region 命名空间

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Sharp.Domain.Model;
using Sharp.Domain.Repositories;
using Sharp.Infrastructure;
using Sharp.Infrastructure.Search;

#endregion

namespace Sharp.Domain.Repository.EF
{
    /// <summary>
    ///     表示实现该接口的类型是应用于某种聚合根的仓储类型。
    /// </summary>
    /// <typeparam name="TAggregateRoot">聚合根类型。</typeparam>
    public interface IRepository<TAggregateRoot> where TAggregateRoot : class, IAggregateRoot
    {
        #region 属性

        /// <summary>
        ///     获取当前仓储所使用的仓储上下文实例。
        /// </summary>
        IRepositoryContext Context { get; }

        #endregion

        #region 方法

        /// <summary>
        ///     将指定的聚合根添加到仓储中。
        /// </summary>
        /// <param name="aggregateRoot">需要添加到仓储的聚合根实例。</param>
        void Add(TAggregateRoot aggregateRoot);

        /// <summary>
        ///     返回一个<see cref="Boolean" />值，该值表示符合指定规约条件的聚合根是否存在。
        /// </summary>
        /// <param name="predicate">表达式。</param>
        /// <returns>如果符合指定规约条件的聚合根存在，则返回true，否则返回false。</returns>
        bool Exists(Expression<Func<TAggregateRoot, bool>> predicate);

        /// <summary>
        ///     将指定的聚合根从仓储中移除。
        /// </summary>
        /// <param name="aggregateRoot">需要从仓储中移除的聚合根。</param>
        void Remove(TAggregateRoot aggregateRoot);

        /// <summary>
        /// 从仓储中移除。
        /// </summary>
        /// <param name="ids"></param>
        void Remove(IEnumerable<Guid> ids);

        /// <summary>
        ///     更新指定的聚合根。
        /// </summary>
        /// <param name="aggregateRoot">需要更新的聚合根。</param>
        void Update(TAggregateRoot aggregateRoot);

        /// <summary>
        ///     Sets modified entity into the repository.
        ///     When calling Commit() method in UnitOfWork
        ///     these changes will be saved into the storage
        /// </summary>
        /// <param name="persisted">The persisted item</param>
        /// <param name="current">The current item</param>
        void Merge(TAggregateRoot persisted, TAggregateRoot current);

        /// <summary>
        ///     根据聚合根的ID值，从仓储中读取聚合根。
        /// </summary>
        /// <param name="key">聚合根的ID值。</param>
        /// <returns>聚合根实例。</returns>
        TAggregateRoot Get(Guid key);

        /// <summary>
        ///     根据聚合根的ID值，从仓储中读取聚合根。
        /// </summary>
        /// <param name="key">聚合根的ID值。</param>
        /// <param name="eagerLoadingProperties"></param>
        /// <returns>聚合根实例。</returns>
        TAggregateRoot Get(Guid key,
            params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties);

        /// <summary>
        ///     根据指定的规约获取聚合根。
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <returns>聚合根。</returns>
        TAggregateRoot Get(Expression<Func<TAggregateRoot, bool>> predicate);

        /// <summary>
        ///     根据指定的规约获取聚合根。
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <param name="eagerLoadingProperties">贪婪加载</param>
        /// <returns>聚合根。</returns>
        TAggregateRoot Get(Expression<Func<TAggregateRoot, bool>> predicate,
            params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties);

        /// <summary>
        ///     根据指定的规约获取聚合根。
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <param name="top">加载多少条数据</param>
        /// <param name="eagerLoadingProperties">贪婪加载</param>
        /// <returns>聚合根。</returns>
        TAggregateRoot Get(Expression<Func<TAggregateRoot, bool>> predicate, int? top = null,
            params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties);

        /// <summary>
        ///     根据指定的规约获取聚合根。
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <param name="top">加载多少条数据</param>
        /// <param name="eagerLoadingProperties">贪婪加载</param>
        /// <returns>聚合根。</returns>
        TAggregateRoot Get(Expression<Func<TAggregateRoot, bool>> predicate, int? top = null,
            params string[] eagerLoadingProperties);

        #region 分页

        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="pageNumber">分页的页码。</param>
        /// <param name="pageSize">分页的页面大小。</param>
        /// <returns>带有分页信息的聚合根集合。</returns>
        PagedResult<TAggregateRoot> Pagging(int pageNumber, int pageSize);

        /// <summary>
        ///  获取分页数据
        /// </summary>
        /// <param name="pageNo">分页的页码。</param>
        /// <param name="pageSize">分页的页面大小。</param>
        /// <param name="orderBy">排序</param>
        /// <returns>带有分页信息的聚合根集合。</returns>
        PagedResult<TAggregateRoot> Pagging(int pageNo, int pageSize, string orderBy);


        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="pageNo">分页的页码。</param>
        /// <param name="pageSize">分页的页面大小。</param>
        /// <param name="predicate">筛选表达式</param>
        /// <param name="sortPredicate">排序表达式。</param>
        /// <returns>所有符合条件的已经排序的聚合根。</returns>
        PagedResult<TAggregateRoot> Pagging(int pageNo, int pageSize,
            Expression<Func<TAggregateRoot, bool>> predicate,
            string sortPredicate);

        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="pf">分页参数</param>
        /// <returns></returns>
        PagedResult<TAggregateRoot> Pagging(PagingFeature pf);

        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="pf"></param>
        /// <param name="predicate">筛选表达式</param>
        /// <param name="eagerLoadingProperties">需要进行饥饿加载的属性Lambda表达式。</param>
        /// <returns>所有符合条件的已经排序的聚合根。</returns>
        PagedResult<TAggregateRoot> Pagging(
            PagingFeature pf,
            Expression<Func<TAggregateRoot, bool>> predicate,
            params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties);

        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="pageNo">分页的页码。</param>
        /// <param name="pageSize">分页的页面大小。</param>
        /// <param name="predicate">筛选表达式</param>
        /// <param name="sortPredicate">排序表达式。</param>
        /// <param name="eagerLoadingProperties">需要进行饥饿加载的属性Lambda表达式。</param>
        /// <returns>所有符合条件的已经排序的聚合根。</returns>
        PagedResult<TAggregateRoot> Pagging(int pageNo, int pageSize,
            Expression<Func<TAggregateRoot, bool>> predicate,
            string sortPredicate,
            params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties);

        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="pf">分页参数。</param>
        /// <param name="predicate">筛选表达式</param>
        /// <param name="sortPredicate">排序表达式。</param>
        /// <param name="eagerLoadingProperties">需要进行饥饿加载的属性Lambda表达式。</param>
        /// <returns>所有符合条件的已经排序的聚合根。</returns>
        PagedResult<TAggregateRoot> Pagging(PagingFeature pf,
            Expression<Func<TAggregateRoot, bool>> predicate,
            string sortPredicate,
            params string[] eagerLoadingProperties);

        #endregion

        #region 获取筛选的指定数据

        #endregion


        #region 获取筛选的对象

        /// <summary>
        ///     从仓储中读取所有聚合根。
        /// </summary>
        /// <returns>所有的聚合根。</returns>
        IList<TAggregateRoot> GetList();

        /// <summary>
        ///     根据指定的规约，从仓储中获取所有符合条件的聚合根。
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <returns>所有符合条件的聚合根。</returns>
        IList<TAggregateRoot> GetList(Expression<Func<TAggregateRoot, bool>> predicate);

        /// <summary>
        ///     以饥饿加载的方式获取所有聚合根。
        /// </summary>
        /// <param name="eagerLoadingProperties">需要进行饥饿加载的属性Lambda表达式。</param>
        /// <returns>所有的聚合根。</returns>
        IList<TAggregateRoot> GetList(params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties);

        IList<TAggregateRoot> GetList(Expression<Func<TAggregateRoot, bool>> predicate, int top, params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties);
        /// <summary>
        ///     以饥饿加载的方式获取聚合根。
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <param name="sort">排序</param>
        /// <param name="top">提取前N条</param>
        /// <param name="eagerLoadingProperties">需要进行饥饿加载的属性Lambda表达式。</param>
        /// <returns>所有的聚合根。</returns>
        IList<TAggregateRoot> GetList(Expression<Func<TAggregateRoot, bool>> predicate, string sort, int? top = null,
            params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties);

        /// <summary>
        ///     以饥饿加载的方式获取聚合根。
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <param name="sort">排序</param>
        /// <param name="top">提取前N条</param>
        /// <param name="eagerLoadingProperties">需要进行饥饿加载的属性Lambda表达式。</param>
        /// <returns>所有的聚合根。</returns>
        IList<TAggregateRoot> GetList(Expression<Func<TAggregateRoot, bool>> predicate, string sort, int? top = null,
            params string[] eagerLoadingProperties);

        #endregion

        #region 统计

        int Count();
        int Count(Expression<Func<TAggregateRoot, bool>> predicate);

        #endregion

        #region 筛选指定数据

        /// <summary>
        /// 筛选指定数据
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="predicate"></param>
        /// <param name="selector"></param>
        /// <param name="top"></param>
        /// <returns></returns>
        IEnumerable<TResult> Select<TResult>(Expression<Func<TAggregateRoot, bool>> predicate,
            Expression<Func<TAggregateRoot, TResult>> selector, int? top = null);

        /// <summary>
        /// 筛选指定数据
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="predicate"></param>
        /// <param name="selector"></param>
        /// <param name="top"></param>
        /// <returns></returns>
        TResult SelectFirst<TResult>(Expression<Func<TAggregateRoot, bool>> predicate,
            Expression<Func<TAggregateRoot, TResult>> selector, int? top = null);

        /// <summary>
        /// 筛选指定数据
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="predicate"></param>
        /// <param name="selector"></param>
        /// <param name="top"></param>
        /// <returns></returns>
        TResult SelectFirstOrDefault<TResult>(Expression<Func<TAggregateRoot, bool>> predicate,
            Expression<Func<TAggregateRoot, TResult>> selector, int? top = null);

        #endregion

        #region 批量插入

        /// <summary>
        /// 批量插入
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="entities"></param>
        void BulkInsertAll(string tableName, IEnumerable<TAggregateRoot> entities);

        #endregion

        #endregion
    }
}